#!/usr/bin/env python

# Copyright JS Foundation and other contributors, http://js.foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#  This file converts ./js/*.js to a C-array in ./source/jerry-targetjs.h file

import argparse
import glob
import os
import re
import sys

special_chars = re.compile(r'[-\\?\'".]')

def extractName(path):
    return special_chars.sub('_', os.path.splitext(os.path.basename(path))[0])

def writeLine(fo, content, indent=0):
    buf = '  ' * indent + content + '\n'
    fo.write(buf)

def regroup(l, n):
    return [ l[i:i+n] for i in range(0, len(l), n) ]

def removeComments(code):
    pattern = r'(\".*?\"|\'.*?\')|(/\*.*?\*/|//[^\r\n]*$)'
    regex = re.compile(pattern, re.MULTILINE | re.DOTALL)
    def _replacer(match):
        if match.group(2) is not None:
            return ""
        else:
            return match.group(1)
    return regex.sub(_replacer, code)

def removeWhitespaces(code):
    return re.sub('\n+', '\n', re.sub('\n +', '\n', code))


LICENSE = '''/* Copyright JS Foundation and other contributors, http://js.foundation
 *
 * Licensed under the Apache License, Version 2.0 (the \"License\");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an \"AS IS\" BASIS
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This file is generated by js2c.py. Please do not modify.
 */

'''

HEADER = '''#ifndef JERRY_TARGETJS_H
#define JERRY_TARGETJS_H

'''

FOOTER = '''
#endif

'''

parser = argparse.ArgumentParser(description="js2c")
parser.add_argument('--build-type', help='build type', default='release', choices=['release', 'debug'])
parser.add_argument('--ignore', help='files to ignore', dest='ignore_files', default=[], action='append')
parser.add_argument('--no-main', help="don't require a 'main.js' file", dest='main', action='store_false', default=True)
parser.add_argument('--js-source', dest='js_source_path', default='./js', help='Source directory of JavaScript files" (default: %(default)s)')
parser.add_argument('--dest', dest='output_path', default='./source', help="Destination directory of 'jerry-targetjs.h' (default: %(default)s)")

args = parser.parse_args()

# argument processing
build_type = args.build_type
ignore_files = args.ignore_files

fout = open(os.path.join(args.output_path, 'jerry-targetjs.h'), 'w')
fout.write(LICENSE);
fout.write(HEADER);

def exportOneFile(path, name):
    fout.write('const static char ' + name + '_n[] = "' + name + '";\n')
    fout.write('const static char ' + name + '_s[] =\n{\n')

    fin = open(path, 'r');
    code = fin.read() + '\0'

    # minimize code when release mode
    if build_type != 'debug':
        code = removeComments(code)
        code = removeWhitespaces(code)

    for line in regroup(code, 10):
        buf = ', '.join(map(lambda ch: format(ord(ch),"#04x"), line))
        if line[-1] != '\0':
            buf += ','
        writeLine(fout, buf, 1)
    writeLine(fout, '};')
    writeLine(fout, 'const static int ' + name + '_l = ' + str(len(code)-1) + ';')
    writeLine(fout, '')

    fin.close();

def exportOneName(name):
    writeLine(fout, '{ ' + name + '_n, ' + name + '_s, ' + name + '_l }, \\', 1)

files = glob.glob(os.path.join(args.js_source_path, '*.js'))
for path in files:
    name = extractName(path)
    if os.path.basename(path) not in ignore_files:
        exportOneFile(path, name)


NATIVE_STRUCT = '''
struct js_source_all {
  const char* name;
  const char* source;
  const int length;
};

#define DECLARE_JS_CODES \\
struct js_source_all js_codes[] = \\
{ \\
'''

fout.write(NATIVE_STRUCT)
if args.main:
    exportOneName('main')
for filename in files:
    name = extractName(filename)
    if name != 'main' and os.path.basename(filename) not in ignore_files:
        exportOneName(name)

writeLine(fout, '{ NULL, NULL, 0 } \\', 1)
writeLine(fout, '};')

fout.write(FOOTER)
fout.close()
